home *** CD-ROM | disk | FTP | other *** search
/ MPEG Toolkit / MPEG Toolkit.iso / win / mpg2w11b / mpeg2ply / mpeg2ply.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-01  |  20.9 KB  |  850 lines

  1. /* patched version from July 13, 1994 */
  2. /* mpeg2dec.c, main(), initialization, option processing                    */
  3.  
  4. /* Copyright (C) 1994, MPEG Software Simulation Group. All Rights Reserved. */
  5.  
  6. /*
  7.  * Disclaimer of Warranty
  8.  *
  9.  * These software programs are available to the user without any license fee or
  10.  * royalty on an "as is" basis.  The MPEG Software Simulation Group disclaims
  11.  * any and all warranties, whether express, implied, or statuary, including any
  12.  * implied warranties or merchantability or of fitness for a particular
  13.  * purpose.  In no event shall the copyright-holder be liable for any
  14.  * incidental, punitive, or consequential damages of any kind whatsoever
  15.  * arising from the use of these programs.
  16.  *
  17.  * This disclaimer of warranty extends to the user of these programs and user's
  18.  * customers, employees, agents, transferees, successors, and assigns.
  19.  *
  20.  * The MPEG Software Simulation Group does not represent or warrant that the
  21.  * programs furnished hereunder are free of infringement of any third-party
  22.  * patents.
  23.  *
  24.  * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
  25.  * are subject to royalty fees to patent holders.  Many of these patents are
  26.  * general enough such that they are unavoidable regardless of implementation
  27.  * design.
  28.  *
  29.  */
  30.  
  31. // MS Windows includes
  32. #include <windows.h>
  33. #include <commdlg.h>
  34. #include <assert.h>
  35. #include <io.h>
  36. #include "gui.h"
  37. #define    APPNAME         "Mpeg2Play"   /* The name of this application */
  38. #define BASEWINDOWTITLE "mpeg2play" /* The title bar text */
  39. #define MAXFILENAME     256  /* maximum length of file pathname */
  40. #define MAXCUSTFILTER   40   /* maximum size of custom filter buffer */
  41.  
  42. // display related variables
  43. #define START    0
  44. #define READY   1
  45. #define PLAYING 2
  46. #define PAUSED  3
  47. #define FINISH  4
  48. #define STOP    5
  49.  
  50.  
  51. #include <stdio.h>
  52. #include <stdlib.h>
  53. #include <ctype.h>
  54. #include <fcntl.h>
  55.  
  56. #define GLOBAL
  57. #include "config.h"
  58. #include "global.h"
  59. #include "mpeg2dec.h"
  60.  
  61. // MS Windows related variables
  62. LRESULT CALLBACK WndProc(
  63.              HWND   hWnd,       // window handle
  64.              UINT   message,    // type of message
  65.              WPARAM uParam,     // additional information
  66.              LPARAM lParam);    // additional information
  67. static HINSTANCE   hInst;          // current instance
  68. static HWND        ghWnd   =NULL;  // handle to main window
  69. static char       *image   =NULL;
  70. static char        szFileName[MAXFILENAME]="";
  71. static unsigned short gusState = START;
  72. static int         nDitherType;
  73. static HDC         hDC;
  74. static HPALETTE    hpal,hPalPrev=NULL;
  75. static PBITMAPINFO pbmi    =NULL;
  76.  
  77. int play_movie(void);
  78. extern int         __argc;
  79. extern char      **__argv;
  80.  
  81. /* private prototypes */
  82. static void initdecoder _ANSI_ARGS_((void));
  83. static void options     _ANSI_ARGS_((int *argcp, char **argvp[]));
  84. static int  getval      _ANSI_ARGS_((char *argv[]));
  85.  
  86. /* loop flag not implemented yet */
  87. static int loopflag;
  88.  
  89. // MS Windows related functions
  90. /////////////////////////////////////////////////////////////////////////////
  91. /*
  92.  *********************************************************************************
  93.  *
  94.  * WinMain:
  95.  *
  96.  *********************************************************************************
  97. */
  98.  
  99. //
  100. // yield function to simulate multitasking on MS Windows
  101. //
  102. static void myYield(void)
  103. {
  104.     MSG         msg;
  105.  
  106.     if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  107.     {
  108.         TranslateMessage(&msg);// Translates virtual key codes
  109.         DispatchMessage(&msg); // Dispatches message to window
  110.     }
  111. }
  112.  
  113. //
  114. // initializations
  115. //
  116. static BOOL InitApplication(HINSTANCE hInstance)
  117. {
  118.    WNDCLASS  wc;
  119.  
  120.    // Fill in window class structure with parameters that describe the
  121.    // main window.
  122.  
  123.    wc.style         = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;// Class style(s).
  124.    wc.lpfnWndProc   = (WNDPROC)WndProc;           // Window Procedure
  125.    wc.cbClsExtra    = 0;                          // No per-class extra data.
  126.    wc.cbWndExtra    = 0;                          // No per-window extra data.
  127.    wc.hInstance     = hInstance;                  // Owner of this class
  128.    wc.hIcon         = LoadIcon (hInstance, APPNAME); // Icon name from .RC
  129.    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);// Cursor
  130.    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);   // Default color
  131.    wc.lpszMenuName  = APPNAME;                    // Menu name from .RC
  132.    wc.lpszClassName = APPNAME;                    // Name to register as
  133.  
  134.    // Register the window class and return success/failure code.
  135.    return (RegisterClass(&wc));
  136. }
  137.  
  138. static BOOL InitInstance(HINSTANCE hInstance,int       nCmdShow)
  139. {
  140.  
  141.     // Save the instance handle in static variable, which will be used in
  142.     // many subsequence calls from this application to Windows.
  143.  
  144.     hInst = hInstance; // Store instance handle in our global variable
  145.  
  146.     // Create a main window for this application instance.
  147.  
  148.     ghWnd = CreateWindow(
  149.              APPNAME,            // See RegisterClass() call.
  150.              BASEWINDOWTITLE,    // Text for window title bar.
  151.              WS_OVERLAPPEDWINDOW &
  152.              ~WS_THICKFRAME &
  153.              ~WS_MAXIMIZEBOX,    // Window style.
  154.              CW_USEDEFAULT,
  155.              0,
  156.              CW_USEDEFAULT,
  157.              0,                  // Use default positioning
  158.              NULL,               // Overlapped windows have no parent.
  159.              NULL,               // Use the window class menu.
  160.              hInstance,          // This instance owns this window.
  161.              NULL                // We don't use any data in our WM_CREATE
  162.     );
  163.  
  164.     // If window could not be created, return "failure"
  165.     if (!ghWnd)
  166.        return (FALSE);
  167.  
  168.     // Make the window visible; update its client area; and return "success"
  169.     ShowWindow(ghWnd, nCmdShow); // Show the window
  170.     UpdateWindow(ghWnd);         // Sends WM_PAINT message
  171.  
  172.     return (TRUE);              // We succeeded...
  173.  
  174. }
  175.  
  176. //
  177. // prompts the user for the efile name
  178. //
  179. static BOOL AskUserFileName(char szFileName[],char szFileTitle[])
  180. {
  181.    /* new variables for common dialogs */
  182.    static char         szFilterSpec[]="MPEG Files\0*.MPG\0MPEG2 Video Files\0*.M2V\0MPEG1 Video Files\0*.M1V\0All Files (*.*)\0*.*\0";
  183.    static char         szInitialDirectory[MAXFILENAME]="";
  184.       OPENFILENAME ofn;
  185.  
  186.    memset(&ofn,0,sizeof(ofn));
  187.  
  188.    /* fill in non-variant fields of OPENFILENAME struct. */
  189.    ofn.lStructSize       = sizeof(OPENFILENAME);
  190.    ofn.hwndOwner         = ghWnd;
  191.    ofn.lpstrFilter       = szFilterSpec;
  192.    ofn.lpstrCustomFilter = NULL;
  193.    ofn.nMaxCustFilter    = 0;
  194.    ofn.nFilterIndex      = 0;
  195.    ofn.lpstrFile         = szFileName;
  196.    ofn.nMaxFile          = MAXFILENAME;
  197.    if (!szInitialDirectory[0])
  198.       GetModuleFileName(hInst, szInitialDirectory, MAXFILENAME);
  199.  
  200.    // strip the file name
  201.    *(LPSTR)strrchr(szInitialDirectory,'\\')=0;
  202.  
  203.    ofn.lpstrInitialDir     = szInitialDirectory;
  204.    ofn.lpstrFileTitle      = szFileTitle;
  205.    ofn.nMaxFileTitle       = MAXFILENAME;
  206.    ofn.lpstrTitle          = NULL;
  207.    ofn.lpstrDefExt         = "MPG";
  208.    ofn.Flags               = 0;
  209. /* changed GetOpenFileName to GetFileName --Chad */
  210.    if (!GetOpenFileName((LPOPENFILENAME)&ofn))
  211.       return FALSE;
  212.  
  213.    // save the current directory
  214.    lstrcpy(szInitialDirectory,szFileName);
  215.    return TRUE;
  216. }
  217.  
  218.  
  219. /*********************************************************************************
  220.  *
  221.  * About box
  222.  *
  223. *********************************************************************************
  224. */
  225.  
  226. BOOL CALLBACK About(HWND   hDlg,         // window handle of the dialog box
  227.             UINT   message,      // type of message
  228.             WPARAM uParam,       // message-specific information
  229.             LPARAM lParam)
  230. {
  231.    switch (message)
  232.    {
  233.       case WM_COMMAND:                     // message: received a command
  234.      if (LOWORD(uParam) == IDOK || LOWORD(uParam) == IDCANCEL)
  235.      {
  236.         EndDialog(hDlg, TRUE);        // Exit the dialog
  237.         return (TRUE);
  238.      }
  239.      break;
  240.    }
  241.    return (FALSE); // Didn't process the message
  242.  
  243.    lParam; // This will prevent 'unused formal parameter' warnings
  244. }
  245.  
  246. //
  247. // Main window procedure
  248. //
  249. LRESULT CALLBACK WndProc(HWND   hWnd,       // window handle
  250.              UINT   message,    // type of message
  251.              WPARAM uParam,     // additional information
  252.              LPARAM lParam)     // additional information
  253. {
  254.    switch (message)
  255.    {
  256.       case WM_CLOSE:
  257.         gusState = STOP;
  258.         myYield();
  259.       return (DefWindowProc(hWnd, message, uParam, lParam));
  260.         break;
  261.  
  262.  
  263.       case WM_DESTROY:  // message: window being destroyed
  264.         gusState = STOP;
  265.         myYield();
  266.       PostQuitMessage(0);
  267.       break;
  268.  
  269.       case WM_COMMAND:  // message: command from application menu
  270.       {
  271.     int wmId, wmEvent;
  272.  
  273.     wmId    = LOWORD(uParam);
  274.     wmEvent = HIWORD(uParam);
  275.  
  276.     switch (wmId)
  277.     {
  278.        case IDM_OPEN:
  279.        {
  280.           char szWindowTitle[80];
  281.           char szFileTitle[MAXFILENAME];
  282.  
  283.            // if something was playing, give a chance to stop.
  284.           if (gusState > READY)
  285.           {
  286.             gusState = STOP;
  287.             myYield();
  288.           }
  289.  
  290.           EnableMenuItem(GetMenu(hWnd), IDM_PLAY, MF_GRAYED | MF_DISABLED);
  291.  
  292.           szFileName[0]=0;
  293.           if (!AskUserFileName (szFileName,szFileTitle))
  294.             return FALSE;
  295.  
  296.           lstrcpy(szWindowTitle, BASEWINDOWTITLE);
  297.           lstrcat(szWindowTitle, " - ");
  298.           lstrcat(szWindowTitle, szFileTitle);
  299.           SetWindowText(hWnd, szFileTitle);
  300.  
  301.           // enable play menu
  302.           EnableMenuItem(GetMenu(hWnd), IDM_PLAY, MF_ENABLED);
  303.  
  304.           gusState = READY;
  305.           break;
  306.        }
  307.  
  308.        case IDM_PLAY:
  309.           // disable play menu while playing
  310.           EnableMenuItem(GetMenu(hWnd), IDM_STOP, MF_ENABLED);
  311.           EnableMenuItem(GetMenu(hWnd), IDM_PLAY, MF_GRAYED | MF_DISABLED);
  312.  
  313.           // play the movie. It returns after the playing ended
  314.           if (play_movie()<0)
  315.               error("error. Movie does not play.");
  316.  
  317.           // disable stop menu
  318.           EnableMenuItem(GetMenu(hWnd), IDM_STOP, MF_GRAYED | MF_DISABLED);
  319.           EnableMenuItem(GetMenu(hWnd), IDM_PLAY, MF_ENABLED);
  320.  
  321.           break;
  322.  
  323.        case IDM_STOP:
  324.           gusState=STOP;
  325.           // force a task switch to allow the decoder to see the stop command
  326.           myYield();
  327.           break;
  328.  
  329.        case IDM_EXIT:
  330.           SendMessage(hWnd, WM_CLOSE, 0, 0l);
  331.           break;
  332.  
  333.        case IDM_ABOUT:
  334.        {
  335.           FARPROC lpProcAbout;  // pointer to the "About" function
  336.  
  337.           lpProcAbout = MakeProcInstance((FARPROC)About, hInst);
  338.           DialogBox(hInst,                 // current instance
  339.             "AboutBox",            // dlg resource to use
  340.             hWnd,                  // parent handle
  341.             (DLGPROC)lpProcAbout); // About() instance address
  342.  
  343.           FreeProcInstance(lpProcAbout);
  344.           break;
  345.        }
  346.  
  347.        case IDM_DISPLAY8:
  348.        case IDM_DISPLAY24:
  349.           // reset the display.
  350.           // It will be reinitialized the first time it will be called
  351.           switch (outtype)
  352.           {
  353.          case T_X11:
  354.            if (nDitherType==8)
  355.               CheckMenuItem(GetMenu(hWnd), IDM_DISPLAY8, MF_UNCHECKED);
  356.            else
  357.               CheckMenuItem(GetMenu(hWnd), IDM_DISPLAY24, MF_UNCHECKED);
  358.            break;
  359.           }
  360.           switch (wmId)
  361.           {
  362.          case IDM_DISPLAY8:
  363.             CheckMenuItem(GetMenu(hWnd), IDM_DISPLAY8, MF_CHECKED);
  364.             outtype=T_X11;
  365.             nDitherType=8;
  366.             break;
  367.  
  368.          case IDM_DISPLAY24:
  369.             CheckMenuItem(GetMenu(hWnd), IDM_DISPLAY24, MF_CHECKED);
  370.             outtype=T_X11;
  371.             nDitherType=24;
  372.             break;
  373.           }
  374.     }
  375.     break;
  376.       }
  377.  
  378.       default:          // Passes it on if unproccessed
  379.     return (DefWindowProc(hWnd, message, uParam, lParam));
  380.    }
  381.    return (0);
  382. }
  383.  
  384. //
  385. // program entry point
  386. //
  387. int APIENTRY WinMain(HINSTANCE   hInstance,
  388.              HINSTANCE   hPrevInstance,
  389.              LPSTR       lpCmdLine,
  390.              int         nCmdShow)
  391. {
  392.     MSG msg;
  393.  
  394.     if (!hPrevInstance)
  395.        // Other instances of app running?
  396.     if (!InitApplication(hInstance))
  397.        // Initialize shared things
  398.        return (FALSE);     // Exits if unable to initialize
  399.  
  400.     /* Perform initializations that apply to a specific instance */
  401.     if (!InitInstance(hInstance, nCmdShow))
  402.        return (FALSE);
  403.  
  404.  
  405.     // start-up initialization
  406.     verbose = 0;
  407.     outtype = T_X11;
  408.     hDC     = GetDC(ghWnd);
  409.     nDitherType=8;
  410.     sflag = 0;
  411.     ld = &base; /* select base layer context */
  412.  
  413. /*    options(&__argc,&__argv);  */
  414.  
  415.     /* Acquire and dispatch messages until a WM_QUIT message is received. */
  416.     while (GetMessage(&msg, // message structure
  417.               NULL,   // handle of window receiving the message
  418.               0,      // lowest message to examine
  419.               0))     // highest message to examine
  420.     {
  421.     TranslateMessage(&msg);// Translates virtual key codes
  422.     DispatchMessage(&msg); // Dispatches message to window
  423.     }
  424.  
  425.     return (msg.wParam); // Returns the value from PostQuitMessage
  426.  
  427.     lpCmdLine; // This will prevent 'unused formal parameter' warnings
  428. }
  429.  
  430. //
  431. // display initialization
  432. //
  433. /* Note: this was already defined in global.h, so
  434.    I commented it out -- Chad  */
  435. /* extern int convmat[][4]; /* defined in display.c */
  436.  
  437. static void init_display(void)
  438. {
  439.   pbmi    = (PBITMAPINFO)malloc(sizeof(BITMAPINFOHEADER) + 240 * sizeof(RGBQUAD));
  440.   pbmi->bmiHeader.biSize = (LONG)sizeof(BITMAPINFOHEADER);
  441.   pbmi->bmiHeader.biPlanes = 1;
  442.   pbmi->bmiHeader.biCompression = 0l;
  443.   pbmi->bmiHeader.biSizeImage = 0l;
  444.   pbmi->bmiHeader.biXPelsPerMeter = 0l;
  445.   pbmi->bmiHeader.biYPelsPerMeter = 0l;
  446.   pbmi->bmiHeader.biClrUsed = 240;
  447.   pbmi->bmiHeader.biClrImportant = 240;
  448.   pbmi->bmiHeader.biBitCount = nDitherType;
  449.   pbmi->bmiHeader.biWidth = coded_picture_width ;
  450.   pbmi->bmiHeader.biHeight= coded_picture_height;
  451.   if ( pbmi->bmiHeader.biBitCount==8 )
  452.   {
  453.      // for 8 BPP, build the color palette
  454.  
  455.      LOGPALETTE *plgpl;
  456.      short      *pPalIndex;
  457.      int         crv, cbu, cgu, cgv;
  458.      int         y, u, v;
  459.      int         i;
  460.  
  461.      plgpl = (LOGPALETTE*) malloc(sizeof(LOGPALETTE) + 240 * sizeof(PALETTEENTRY));
  462.      plgpl->palNumEntries = 240;
  463.      plgpl->palVersion = 0x300;
  464.      pPalIndex=(short *)pbmi->bmiColors;
  465.  
  466.      /* matrix coefficients */
  467.      crv = convmat[matrix_coefficients][0];
  468.      cbu = convmat[matrix_coefficients][1];
  469.      cgu = convmat[matrix_coefficients][2];
  470.      cgv = convmat[matrix_coefficients][3];
  471.  
  472.      for (i=16; i<240; i++)
  473.      {
  474.        /* color space conversion */
  475.        y = 16*((i>>4)&15) + 8;
  476.        u = 32*((i>>2)&3)  - 48;
  477.        v = 32*(i&3)       - 48;
  478.  
  479.        y = 76309 * (y - 16); /* (255/219)*65536 */
  480.  
  481.        plgpl->palPalEntry[i].peRed   = clp[(y + crv*v + 32768)>>16];
  482.        plgpl->palPalEntry[i].peGreen = clp[(y - cgu*u -cgv*v + 32768)>>16];
  483.        plgpl->palPalEntry[i].peBlue  = clp[(y + cbu*u + 32786)>>16];
  484.        pPalIndex[i]=i;
  485.      }
  486.      hpal = CreatePalette(plgpl);
  487.      free(plgpl);
  488.      hPalPrev=SelectPalette(hDC,hpal,FALSE);
  489.      RealizePalette(hDC);
  490.   }
  491. }
  492.  
  493. //
  494. // display clean-up
  495. //
  496. static void exit_display()
  497. {
  498.    if (pbmi)
  499.    {
  500.       free(pbmi);
  501.       pbmi=NULL;
  502.    }
  503.    if (hPalPrev)
  504.    {
  505.        SelectPalette(hDC,hPalPrev,FALSE);
  506.        DeleteObject(hpal);
  507.        hPalPrev=NULL;
  508.    }
  509. }
  510.  
  511. //
  512. // display the image on the MS Windows screen
  513. //
  514. void display_image(dithered_image)
  515. unsigned char *dithered_image;
  516. {
  517.   /* display dithered image */
  518.   SetDIBitsToDevice(hDC,0,0,coded_picture_width,coded_picture_height,
  519.              0,0,0,coded_picture_height,dithered_image,pbmi,DIB_PAL_COLORS);
  520. }
  521.  
  522.  
  523.  
  524. //
  525. // decode a file and store and/or display it
  526. //
  527.  
  528. int play_movie(void)
  529. {
  530.   int framenum, first;
  531.  
  532.   /* open MPEG input file(s) */
  533.   if ((base.infile=open(szFileName,O_RDONLY|O_BINARY))<0)
  534.   {
  535.     sprintf(errortext,"Input file %s not found\n",szFileName);
  536.     error(errortext);
  537.   }
  538.  
  539.   /* Look for Systems start code */
  540.   sysstream = 0;
  541. //  if (base.infile != 0)
  542.   {
  543.     initbits();
  544.     startcode();
  545.     switch(showbits(32))
  546.     {
  547.     case SEQ_START_CODE:
  548.       break;
  549.     case PACK_START_CODE:
  550.       sysstream = 1;
  551.       break;
  552.     default:
  553.       error("This not a valid MPEG system or video stream\n");
  554.       break;
  555.     }
  556.     lseek(base.infile,0l,0);
  557.     initbits();
  558.   }
  559.  
  560.  first = 1;
  561.  
  562.   do
  563.   {
  564.     /* (re)set to begin of file */
  565.  
  566.     ld = &base;
  567. //    if (base.infile!=0)
  568.       lseek(base.infile,0l,0);
  569.     initbits();
  570.  
  571.  
  572. /*  Enhancement currently commented out
  573.     if (twostreams)
  574.     {
  575.       ld = &enhan;
  576.       lseek(enhan.infile,0l,0);
  577.       initbits();
  578.       ld = &base;
  579.     }
  580.     End of commented out section */
  581.  
  582.     framenum = 0;
  583.  
  584.     while (getheader())
  585.     {
  586.       if (first)
  587.       {
  588.  
  589.         RECT wr,cr;
  590.         int  d;
  591.  
  592.         // size window to film size
  593.         SetRect(&cr,0,0,horizontal_size,vertical_size);
  594.         wr=cr;
  595.         AdjustWindowRect(&wr,GetWindowLong(ghWnd,GWL_STYLE),TRUE);
  596.         OffsetRect(&wr,-wr.left,-wr.top);
  597.         SetWindowPos(ghWnd,HWND_TOP,0,0,wr.right,wr.bottom,SWP_NOMOVE);
  598.  
  599.         // for QSIF movies the menu will wrap around so we need
  600.         // to increase the height of the window
  601.         GetClientRect(ghWnd, &wr);
  602.         d=cr.bottom-(wr.bottom-wr.top);
  603.  
  604.         if (d>0)
  605.         {
  606.           GetWindowRect(ghWnd, &wr);
  607.           SetWindowPos(ghWnd,HWND_TOP,0,0,wr.right-wr.left,wr.bottom-wr.top+d,SWP_NOMOVE);
  608.         }
  609.  
  610.         initdecoder();
  611.  
  612.         if (outtype==T_X11)
  613.         {
  614.           init_dither(nDitherType);
  615.           init_display();
  616.         }
  617.  
  618.         first = 0;
  619.       }
  620.  
  621.       getpicture(framenum);
  622.  
  623.       if (!secondfield)
  624.       {
  625.         framenum++;
  626.       }
  627.  
  628.       // give the user a chance to perform something
  629.       myYield();
  630.       if (gusState==STOP)
  631.         break;
  632.     }
  633.  
  634.     if (framenum!=0)
  635.     {
  636.       /* put last frame */
  637.       putlast(framenum);
  638.     }
  639.  
  640.   }
  641.   while (loopflag);
  642.  
  643. //  if (base.infile!=0)
  644.     close(base.infile);
  645.  
  646.   if (outtype==T_X11)
  647.     exit_display();
  648.  
  649.   return 0;
  650. }
  651.  
  652.  
  653. /////////////////////////////////////////////////////////////////////
  654. //
  655. // MPEG related functions
  656. //
  657. // (portable)
  658. //
  659. static void initdecoder()
  660. {
  661.   int i, cc, size;
  662.   static int blk_cnt_tab[3] = {6,8,12};
  663.  
  664.   /* check scalability mode of enhancement layer */
  665.   if (twostreams && enhan.scalable_mode!=SC_SNR &&
  666.      !(base.scalable_mode==SC_DP && base.scalable_mode==SC_DP))
  667.     error("unsupported scalability mode\n");
  668.  
  669.   /* clip table */
  670.   if (!(clp=(unsigned char *)malloc(1024)))
  671.     error("malloc failed\n");
  672.  
  673.   clp += 384;
  674.  
  675.   for (i=-384; i<640; i++)
  676.     clp[i] = (i<0) ? 0 : ((i>255) ? 255 : i);
  677.  
  678.   /* force MPEG-1 parameters */
  679.   if (!base.mpeg2)
  680.   {
  681.     prog_seq = 1;
  682.     prog_frame = 1;
  683.     pict_struct = FRAME_PICTURE;
  684.     frame_pred_dct = 1;
  685.     chroma_format = CHROMA420;
  686.     matrix_coefficients = 5;
  687.   }
  688.  
  689.   /* round to nearest multiple of coded macroblocks */
  690.   mb_width = (horizontal_size+15)/16;
  691.   mb_height = (base.mpeg2 && !prog_seq) ? 2*((vertical_size+31)/32)
  692.                     : (vertical_size+15)/16;
  693.   coded_picture_width = 16*mb_width;
  694.   coded_picture_height = 16*mb_height;
  695.  
  696.   chrom_width = (chroma_format==CHROMA444) ? coded_picture_width
  697.                        : coded_picture_width>>1;
  698.   chrom_height = (chroma_format!=CHROMA420) ? coded_picture_height
  699.                         : coded_picture_height>>1;
  700.   blk_cnt = blk_cnt_tab[chroma_format-1];
  701.  
  702.   for (cc=0; cc<3; cc++)
  703.   {
  704.     if (cc==0)
  705.       size = coded_picture_width*coded_picture_height;
  706.     else
  707.       size = chrom_width*chrom_height;
  708.  
  709.     if (!(refframe[cc] = (unsigned char *)malloc(size)))
  710.       error("malloc failed\n");
  711.  
  712.     if (!(oldrefframe[cc] = (unsigned char *)malloc(size)))
  713.       error("malloc failed\n");
  714.  
  715.     if (!(auxframe[cc] = (unsigned char *)malloc(size)))
  716.       error("malloc failed\n");
  717.  
  718.     if (base.scalable_mode==SC_SPAT)
  719.     {
  720.       /* this assumes lower layer is 4:2:0 */
  721.       if (!(llframe0[cc] = (unsigned char *)malloc((llw*llh)/(cc?4:1))))
  722.     error("malloc failed\n");
  723.       if (!(llframe1[cc] = (unsigned char *)malloc((llw*llh)/(cc?4:1))))
  724.     error("malloc failed\n");
  725.     }
  726.   }
  727.  
  728.   if (base.scalable_mode==SC_SPAT)
  729.   {
  730.     if (!(lltmp = (short *)malloc(llw*((llh*vn)/vm)*sizeof(short))))
  731.       error("malloc failed\n");
  732.   }
  733.  
  734.   /* IDCT */
  735.   init_idct();
  736. }
  737.  
  738. void error(text)
  739. char *text;
  740. {
  741.   fprintf(stderr,text);
  742.   exit(1);
  743. }
  744.  
  745. /* compliance warning messages to user, but don't exit() */
  746. void warning(text)
  747. char *text;
  748. {
  749.   if (!quiet)
  750.   {
  751.     fprintf(stderr,"%s\n",text);
  752.   }
  753. }
  754.  
  755. #ifdef TRACE
  756. /* trace output */
  757. void printbits(code,bits,len)
  758. int code,bits,len;
  759. {
  760.   int i;
  761.   for (i=0; i<len; i++)
  762.     printf("%d",(code>>(bits-1-i))&1);
  763. }
  764. #endif
  765.  
  766. /* option processing */
  767. /*
  768. static void options(argcp,argvp)
  769. int *argcp;
  770. char **argvp[];
  771. {
  772.   outtype = T_X11;
  773.  
  774.   while (*argcp>1 && (*argvp)[1][0]=='-')
  775.   {
  776.     while ((*argvp)[1][1])
  777.     {
  778.       switch (toupper((*argvp)[1][1]))
  779.       {
  780.       case 'V':
  781.     verbose = getval(*argvp);
  782.     break;
  783.       case 'O':
  784.     outtype = getval(*argvp);
  785.     break;
  786.       case 'L':
  787.     loopflag = 1;
  788.     break;
  789.       case 'S':
  790.     sflag = 1;
  791.     break;
  792. #ifdef TRACE
  793.       case 'T':
  794.     trace = 1;
  795.     break;
  796. #endif
  797.       case 'Q':
  798.     quiet = 1;
  799.     break;
  800.       default:
  801.     fprintf(stderr,"undefined option -%c ignored\n",(*argvp)[1][1]);
  802.       }
  803.  
  804.       (*argvp)[1]++;
  805.     }
  806.  
  807.     (*argvp)++;
  808.     (*argcp)--;
  809.   }
  810.  
  811.   if (sflag)
  812.   {
  813.     /* input file for spatial prediction */
  814. /*    llinputname = (*argvp)[1];
  815.     (*argvp)++;
  816.     (*argcp)--;
  817.   }
  818.  
  819. #if 0
  820.   if (*argcp!=2 && *argcp!=3)
  821.   {
  822.     printf("\n%s, %s\n",version,author);
  823.     printf("Usage:   mpeg2play {options} input.m2v {upper.m2v}\n\
  824. Options: -vn  verbose output (n: level)\n\
  825.      -on  output format (0: X11 (default), 1: none\n\
  826.      -l   loop sequence\n\
  827.      -q   quiet (no error output)\n\
  828.      -s infile  spatial scalable sequence\n");
  829.     exit(0);
  830.   }
  831. #endif
  832. }
  833. */
  834.  
  835. static int getval(argv)
  836. char *argv[];
  837. {
  838.   int val;
  839.  
  840.   if (sscanf(argv[1]+2,"%d",&val)!=1)
  841.     return 0;
  842.  
  843.   while (isdigit(argv[1][2]))
  844.     argv[1]++;
  845.  
  846.   return val;
  847. }
  848.  
  849.  
  850.